using System;
using System.Collections.Generic;
using NaughtyAttributes;
using UnityEngine;

namespace Gj
{
    public class AnimationManagerHelper : MonoBehaviour
    {
        [Serializable]
        public class AnimationManagerItem
        {
            public string key;
            public List<AnimationHelper> list;
            public List<AnimationManagerHelper> managerList;
            public List<AnimationEffect> effectList;
            public AudioClip clip;
            public SoundType soundType;
        }
        
        public bool autoPlay = true;
        public float delayTime = 0;
        public GameObject target;
        public bool self;
        public AudioClip clip;
        public SoundType soundType;
        public List<AnimationHelper> list;
        public List<AnimationManagerHelper> managerList;
        public List<AnimationEffect> effectList;
        public List<AnimationManagerItem> map;

        private void Awake()
        {
            Init();
            if (autoPlay) Play();
        }

        private void Init()
        {
            if (target != null)
            {
                SetTarget(target);
            }
        }

        public void SetTarget(GameObject t)
        {
            for (var i = 0; i < list.Count; i++) list[i].SetTarget(t);
            for (var i = 0; i < managerList.Count; i++) managerList[i].SetTarget(t);
            for (int i = 0; i < map.Count; i++)
            {
                for (var j = 0; j < map[i].list.Count; j++) map[i].list[j].SetTarget(t);
                for (var j = 0; j < map[i].managerList.Count; j++) map[i].managerList[j].SetTarget(t);
            }
        }

        public void SetNotice(AnimationHelper.Notice notice)
        {
            for (var i = 0; i < list.Count; i++) list[i].SetNotice(notice);
            for (var i = 0; i < managerList.Count; i++) managerList[i].SetNotice(notice);
            for (int i = 0; i < map.Count; i++)
            {
                for (var j = 0; j < map[i].list.Count; j++) map[i].list[j].SetNotice(notice);
                for (var j = 0; j < map[i].managerList.Count; j++) map[i].managerList[j].SetNotice(notice);
            }
        }

        [Button]
        public void Forward()
        {
            if (soundType != SoundType.None)
                Game.single.PlayEFF(soundType);
            else if (clip != null) Game.single.PlayEFF(clip);
            
            for (var i = 0; i < list.Count; i++) list[i].Forward();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Forward();
            
            for (var i = 0; i < effectList.Count; i++) effectList[i].Play();
        }

        [Button]
        public void Backward()
        {
            if (soundType != SoundType.None)
                Game.single.PlayEFF(soundType);
            else if (clip != null) Game.single.PlayEFF(clip);
            
            for (var i = 0; i < list.Count; i++) list[i].Backward();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Backward();
            
            for (var i = 0; i < effectList.Count; i++) effectList[i].Play();
        }
        
        public void Restore()
        {
            for (var i = 0; i < list.Count; i++) list[i].Restore();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Restore();
        }

        public void End()
        {
            Stop();
        }

        public void Play()
        {
            if (delayTime > 0) Invoke(nameof(PlayAll), delayTime);
            else PlayAll();
        }

        void PlayAll()
        {
            if (soundType != SoundType.None)
                Game.single.PlayEFF(soundType);
            else if (clip != null) Game.single.PlayEFF(clip);
            
            for (var i = 0; i < list.Count; i++) list[i].Play();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Play();
            
            for (var i = 0; i < effectList.Count; i++) effectList[i].Play();
        }

        public void Pause()
        {
            for (var i = 0; i < list.Count; i++) list[i].Pause();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Pause();
        }

        public void Stop()
        {
            for (var i = 0; i < list.Count; i++) list[i].Stop();

            for (var i = 0; i < managerList.Count; i++) managerList[i].Stop();
            
            for (var i = 0; i < effectList.Count; i++) effectList[i].Stop();
        }

        public void Play(string key)
        {
            for (int i = 0; i < map.Count; i++)
            {
                if (map[i].key == key)
                {
                    Play(map[i]);
                    return;
                }
            }
        }

        public void Stop(string key)
        {
            for (int i = 0; i < map.Count; i++)
            {
                if (map[i].key == key)
                {
                    Stop(map[i]);
                    return;
                }
            }
        }

        public void Play(AnimationManagerItem item)
        {
            if (item.soundType != SoundType.None)
                Game.single.PlayEFF(item.soundType);
            else if (item.clip != null) Game.single.PlayEFF(item.clip);
            
            for (var i = 0; i < item.list.Count; i++) item.list[i].Play();

            for (var i = 0; i < item.managerList.Count; i++) item.managerList[i].Play();
            
            for (var i = 0; i < item.effectList.Count; i++) item.effectList[i].Play();
        }

        public void Stop(AnimationManagerItem item)
        {
            for (var i = 0; i < item.list.Count; i++) item.list[i].Stop();

            for (var i = 0; i < item.managerList.Count; i++) item.managerList[i].Stop();
            
            for (var i = 0; i < item.effectList.Count; i++) item.effectList[i].Stop();
        }
    }
}